package main

/*******************************************************************************
Copyright:cloud
Author:cloudapex@126.com
Version:1.0
Date:2014-10-18
Description:协议生成器
	依赖：官方protoc.exe GitHub上protobuf的库编译出protoc-gen-go.exe 以及 proto.a 以及此源码编译出的工具GPack.exe
	# 本程序的执行目录为顶层协议文件夹
		work_dir(工具在此目录下执行)
			|-- Msg_proto_dir1	// 目录必须是[Message|Msg]作为前缀
				|-- MessageId.h 	// 0 必须有一个定义协议号的文件
				|-- Msgxxxxx1.proto // 1 文件名必须是[Msg]作为前缀
				|-- Msgxxxxx2-.proto// 2 如果文件名包含'-'符号,则认为是备份文件,不参与编译
				|-- Msgxxxxx3.proto	// 3 文件内定义的协议名称 必须以[Msg]作为前缀
				|-- [...]			// 4 文件内的协议名称以驼峰式的写法,工具会自动转换为'_'拼接的全大写的字符串作为协议类型名
			|-- Msg_proto_dir2
			|-- Msg_proto_dir3
			MessageCommon.proto		// 存放公共结构或枚举定义
		>生成目标:./output(可以指定)/Protocols.对应语言后缀
	# Exec: GPack -o=./  -t=go -p=pack -path=C:\\Users\\cloud\\Golang\\src -pack=gitee.com/cloudapex/Ghost/ntc

	# Exec: GPack -o=./  -t=gd -p=pack -path=C:\\Users\\cloud\\Golang\\src -pack=gitee.com/cloudapex/Ghost/ntc -dir=MsgClient

	# GPack -o=./  -t=go -p=pack -path=D:/Golang/library -pack=gitee.com/cloudapex/Ghost/ntc

	# For Go about Enum:
		如果是Msg内部的枚举 -> 砍掉 Msg前缀 更换E , 去掉_符号直接拼装. eg: EForwardMessageErrRet(MsgForwardMessage)
*******************************************************************************/

import (
	"flag"
	"fmt"
	"os"

	"gitee.com/cloudapex/Ghost/utd"
)

// flag var
var (
	vTargetLang  string
	vPacketName  string
	vOutputsDir  string
	vImportPacks utd.TStringArray
	vImportPaths utd.TStringArray
	vIncludeDirs utd.TStringArray
)

func init() {
	flag.StringVar(&vTargetLang, "t", "go", "指定为哪个语言编译[go|csharp|cpp|gd ]")
	flag.StringVar(&vPacketName, "p", "pkg", "指定编译出的库(包)的名字[pack]")
	flag.StringVar(&vOutputsDir, "o", "", "指定编译出的文件存放目录")

	flag.Var(&vImportPaths, "path", "导入外部proto文件所在目录[可多次]")
	flag.Var(&vImportPacks, "pack", "包含的其他包名称[可多次]")
	flag.Var(&vIncludeDirs, "dir", "指定编译哪个子目录名(默认包含所有子目录)[可多次]")
}

func main() {

	// 启动参数
	if flag.Parse(); flag.NFlag() == 0 {
		tips := "Listed below are all the options parameter:\n"
		flag.VisitAll(func(f *flag.Flag) {
			tips += fmt.Sprintf("    -%-10s %10s(default) tips:%s\n", f.Name, f.DefValue, f.Usage)
		})
		fmt.Println("Init parameter error, Please refer to :\n", tips)
		return
	}

	fmt.Println(">>>>>>>>>>初始化环境...")
	if err := InitBuildEnviron(); err != nil {
		fmt.Println("初始化环境[ERROR]:", err)
		return
	}

	fmt.Printf("准备编译 -> 目标语言[%s] + 目标包名[%s] + 目标文件[%s]\n", vTargetLang, vPacketName, TargetFile)

	fmt.Println(">>>>>>>>>>收集协议结构和类型...")
	if err := MakeMsgTypeAndName(); err != nil {
		fmt.Println("收集消息结构和类型[ERROR]:", err)
		return
	}

	fmt.Println(">>>>>>>>>>合并文件...")
	if err := MergeAllProtoFiles(); err != nil {
		fmt.Println("合并文件[ERROR]:", err)
		return
	}

	fmt.Println(">>>>>>>>>>制作协议...")
	if err := MakeProtoHandleFun(); err != nil {
		fmt.Println("制作协议[ERROR]:", err)
		return
	}

	// 移除 Protocols.proto
	os.Remove(fmt.Sprintf("./%s.%s", FILE_NAME_PROTO, FILE_PROTO_SUFFIX))

	fmt.Println(">>>>>>>>>>编译完成=OK!", "<", vTargetLang, ">")
}
